#include "BieuThuc.h"
BieuThucHang* BieuThucHang::ZERO = NULL;
BieuThuc* BieuThuc::tinhDaoHam(){
	if(bieuThuc == NULL){
		bieuThuc = this->timDaoHam();
	}
	return bieuThuc;
}

BieuThuc::BieuThuc(){
	bieuThuc = NULL;
}

//BieuThuc::~BieuThuc(){
//}

BieuThucHang::BieuThucHang(){
	hangSo = 0;
}

BieuThucHang::BieuThucHang(double hangSo){
	this->hangSo = hangSo;
}

double BieuThucHang::tinhGiaTri(double x){
	return hangSo;
}

//BieuThuc* BieuThucHang::tinhDaoHam(){
//	BieuThuc* kq = new BieuThucHang();
//	return kq;
//}

BieuThuc* BieuThucHang::timDaoHam(){
	BieuThuc* kq = new BieuThucHang();
	return kq;
}

void BieuThucHang::daoDauBieuThuc(){
	this->hangSo = hangSo * (-1);
}

string BieuThucHang::xuatChuoi(){
	std::ostringstream sstr;

	if(this->hangSo == 0 || this == NULL)
		return "";
	else{
		sstr << hangSo;
		return sstr.str();
	}
}

BieuThucDon::BieuThucDon(){
	heSo = 0;
	soMu = 1;
}

BieuThucDon::BieuThucDon(double heSo, double soMu){
	this->heSo = heSo;
	this->soMu = soMu;
}

double BieuThucDon::tinhGiaTri(double x){
	double kq = 1;
	for(int i=0; i<soMu; i++)
	{
		kq = kq*x;
	}
	return heSo*kq;
}

//BieuThuc* BieuThucDon::tinhDaoHam(){
//	double heSoMoi = heSo*soMu;
//	double soMuMoi = soMu - 1;
//
//	BieuThuc* btkq = new BieuThucDon(heSoMoi, soMuMoi);
//	return btkq;
//}

BieuThuc* BieuThucDon::timDaoHam(){
	double heSoMoi = heSo*soMu;
	double soMuMoi = soMu - 1;

	BieuThuc* btkq = new BieuThucDon(heSoMoi, soMuMoi);
	return btkq;
}

void BieuThucDon::daoDauBieuThuc(){
	this->heSo = heSo * (-1);
}

string BieuThucDon::xuatChuoi(){
	std::ostringstream sstr;
	std::ostringstream sstr1;
	if(this->heSo == 0){
		return "";
	}
	else{
		if(this->soMu == 0){
			sstr << heSo;
			return sstr.str();
		}
		else{
			if(this->soMu == 1){
				sstr << heSo;
				return sstr.str() + "x";
			}
			else{
				sstr << heSo;
				sstr1 << soMu;
				return sstr.str() + "x^" + sstr1.str();
			}
		}
	}
}

BieuThucTong::BieuThucTong(){
}

BieuThucTong::BieuThucTong(BieuThuc* bt1, BieuThuc* bt2){
	this->bieuThuc1 = bt1;
	this->bieuThuc2 = bt2;
}

BieuThucTong::~BieuThucTong(){
	delete bieuThuc1;
	delete bieuThuc2;
}

double BieuThucTong::tinhGiaTri(double x){
	return bieuThuc1->tinhGiaTri(x) + bieuThuc2->tinhGiaTri(x);
}

//BieuThuc* BieuThucTong::tinhDaoHam(){
//	BieuThuc* daoHambt1 = bieuThuc1->tinhDaoHam();
//	BieuThuc* daoHambt2 = bieuThuc2->tinhDaoHam();
//
//	BieuThuc* kq = new BieuThucTong(daoHambt1, daoHambt2);
//	return kq;
//}
BieuThuc* BieuThucTong::timDaoHam(){
	BieuThuc* daoHambt1 = bieuThuc1->tinhDaoHam();
	BieuThuc* daoHambt2 = bieuThuc2->tinhDaoHam();

	BieuThuc* kq = new BieuThucTong(daoHambt1, daoHambt2);
	return kq;
}

void BieuThucTong::daoDauBieuThuc()
{
	bieuThuc1->daoDauBieuThuc();
	bieuThuc2->daoDauBieuThuc();
}

string BieuThucTong::xuatChuoi(){
	string kqbt1 = bieuThuc1->xuatChuoi();
	string kqbt2 = bieuThuc2->xuatChuoi();
	if(kqbt1 == ""){
		return kqbt2;
	}
	else{
		if(kqbt2 == ""){
			return kqbt1;
		}
		else{
			return "(" + kqbt1  + "+" + kqbt2 + ")";
		}
	}
}

BieuThucTich::BieuThucTich(){
}

BieuThucTich::BieuThucTich(BieuThuc* bt1, BieuThuc* bt2){
	this->bieuThuc1 = bt1;
	this->bieuThuc2 = bt2;
}

BieuThucTich::~BieuThucTich(){
	delete bieuThuc1;
	delete bieuThuc2;
}

double BieuThucTich::tinhGiaTri(double x){
	return bieuThuc1->tinhGiaTri(x) * bieuThuc2->tinhGiaTri(x);
}

//BieuThuc* BieuThucTich::tinhDaoHam(){
//	BieuThuc* daoHambt1 = bieuThuc1->tinhDaoHam();
//	BieuThuc* daoHambt2 = bieuThuc2->tinhDaoHam();
//
//	BieuThuc* tich1 = new BieuThucTich(daoHambt1, bieuThuc2);
//	BieuThuc* tich2 = new BieuThucTich(daoHambt2, bieuThuc1);
//
//	BieuThuc* kq = new BieuThucTong(tich1, tich2);
//	return kq;
//}

BieuThuc* BieuThucTich::timDaoHam(){
	BieuThuc* daoHambt1 = bieuThuc1->tinhDaoHam();
	BieuThuc* daoHambt2 = bieuThuc2->tinhDaoHam();

	BieuThuc* tich1 = new BieuThucTich(daoHambt1, bieuThuc2);
	BieuThuc* tich2 = new BieuThucTich(daoHambt2, bieuThuc1);

	BieuThuc* kq = new BieuThucTong(tich1, tich2);
	return kq;
}

void BieuThucTich::daoDauBieuThuc(){
	bieuThuc1->daoDauBieuThuc();
}

string BieuThucTich::xuatChuoi(){
	string kqbt1 = bieuThuc1->xuatChuoi();
	string kqbt2 = bieuThuc2->xuatChuoi();
	if(kqbt1 == "" || kqbt2 == ""){
		return "";
	}
	else{
		if(kqbt1 == kqbt2){
			return "(" + kqbt1 + ")^2";
		}
		else{
		return "(" + kqbt1 + "*" + kqbt2 + ")";
		}
	}
}

BieuThucChia::BieuThucChia(){
}

BieuThucChia::BieuThucChia(BieuThuc* bt1, BieuThuc* bt2){
	this->bieuThuc1 = bt1;
	this->bieuThuc2 = bt2;
}

BieuThucChia::~BieuThucChia(){
	delete bieuThuc1;
	delete bieuThuc2;
}

double BieuThucChia::tinhGiaTri(double x){
	return bieuThuc1->tinhGiaTri(x) / bieuThuc2->tinhGiaTri(x);
}

//BieuThuc* BieuThucChia::tinhDaoHam(){
//	BieuThuc* daoHambt1 = bieuThuc1->tinhDaoHam();
//	BieuThuc* daoHambt2 = bieuThuc2->tinhDaoHam();
//
//	BieuThuc* tich1 = new BieuThucTich(daoHambt1, bieuThuc2);
//	bieuThuc1->daoDauBieuThuc();
//	BieuThuc* tich2 = new BieuThucTich(daoHambt2, bieuThuc1);
//
//	BieuThuc* kqTu = new BieuThucTong(tich1, tich2);
//	BieuThuc* kqMau = new BieuThucTich(bieuThuc2, bieuThuc2);
//
//	BieuThuc* kq = new BieuThucChia(kqTu, kqMau);
//	return kq;
//}

BieuThuc* BieuThucChia::timDaoHam(){
	BieuThuc* daoHambt1 = bieuThuc1->tinhDaoHam();
	BieuThuc* daoHambt2 = bieuThuc2->tinhDaoHam();

	BieuThuc* tich1 = new BieuThucTich(daoHambt1, bieuThuc2);
	bieuThuc1->daoDauBieuThuc();
	BieuThuc* tich2 = new BieuThucTich(daoHambt2, bieuThuc1);

	BieuThuc* kqTu = new BieuThucTong(tich1, tich2);
	BieuThuc* kqMau = new BieuThucTich(bieuThuc2, bieuThuc2);

	BieuThuc* kq = new BieuThucChia(kqTu, kqMau);
	return kq;
}

void BieuThucChia::daoDauBieuThuc(){
	bieuThuc1->daoDauBieuThuc();
}

string BieuThucChia::xuatChuoi(){
	string kqbt1 = bieuThuc1->xuatChuoi();
	string kqbt2 = bieuThuc2->xuatChuoi();
	if(kqbt1 == ""){
		return "";
	}
	else{
		if(kqbt2 == ""){
			return kqbt1;
		}
		else{
			return "(" + kqbt1 + "/" + kqbt2 + ")";
		}
	}
}